package app.common.utils.dingtalk;

import com.aliyun.dingtalkworkflow_1_0.Client;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponse;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
import com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsResponse;
import com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.gitee.feizns.dynamic.DateUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 工作流相关工具类
 * @author feizns
 * @since 2022/11/9
 */
public class WorkflowUtils {

    /**
     * 用户工具类
     */
    private final Auth2Utils auth2Utils;

    public WorkflowUtils(Auth2Utils auth2Utils) {
        this.auth2Utils = auth2Utils;
    }

    /**
     * 使用 Token 初始化账号Client
     * @return Client
     */
    public static Client createClient() throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.protocol = "https";
        config.regionId = "central";
        return new Client(config);
    }

    /**
     * 获取审批实例ID列表（120前到今天的数据）
     * @param processCode 流程码
     * @param nextToken 下次游标（如果为null表示没有数据了）
     * @return 返回流程实例编号列表
     * @throws TeaException 含有 code 和 message 属性，可帮助开发定位问题
     * @throws Exception 请求异常
     */
    public ListProcessInstanceIdsResponseBody.ListProcessInstanceIdsResponseBodyResult getProcessInstanceIds(String processCode, Long nextToken) throws Exception {
        return getProcessInstanceIds(processCode, LocalDateTime.now().minusDays(120), nextToken);
    }

    /**
     * 获取审批实例ID列表
     * @param processCode 流程码
     * @param startTime 开始时间
     * @param nextToken 下次游标（如果为null表示没有数据了）
     * @return 返回流程实例编号列表
     * @throws TeaException 含有 code 和 message 属性，可帮助开发定位问题
     * @throws Exception 请求异常
     * @apiNote 如果只传入startTime参数，要求时间距离当前时间不能超过120天，endTime不传则默认取当前时间。
     */
    public ListProcessInstanceIdsResponseBody.ListProcessInstanceIdsResponseBodyResult getProcessInstanceIds(String processCode, LocalDateTime startTime, Long nextToken) throws Exception {
        Client client = createClient();
        com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsHeaders listProcessInstanceIdsHeaders = new com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsHeaders();
        listProcessInstanceIdsHeaders.xAcsDingtalkAccessToken = auth2Utils.getAccessToken();
        com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsRequest listProcessInstanceIdsRequest = new com.aliyun.dingtalkworkflow_1_0.models.ListProcessInstanceIdsRequest()
                .setProcessCode(processCode)
                //如果只传入startTime参数，要求时间距离当前时间不能超过120天，endTime不传则默认取当前时间。
                .setStartTime(DateUtils.milliseconds(startTime))
                .setMaxResults(20L);//默认分页20条
        nextToken = nextToken != null ? nextToken : 0;  //默认第一页
        listProcessInstanceIdsRequest.setNextToken(nextToken);
        ListProcessInstanceIdsResponse idsResponse = client.listProcessInstanceIdsWithOptions(listProcessInstanceIdsRequest, listProcessInstanceIdsHeaders, new RuntimeOptions());
        return idsResponse.getBody().getResult();
    }

    /**
     * 获取所有的审批实例ID列表（120天前到现在的数据）
     * @param processCode 流程编号
     * @return 返回实例编号列表
     * @throws Exception 请求异常
     */
    public List<String> getProcessInstanceIdsFrom120DaysAgo(String processCode) throws Exception {
        return getProcessInstanceIds(processCode, LocalDateTime.now().minusDays(120));
    }

    /**
     * 获取今天所有的审批实例ID列表（今日零点到现在的数据）
     * @param processCode 流程编号
     * @return 返回实例编号列表
     * @throws Exception 请求异常
     */
    public List<String> getProcessInstanceIds(String processCode) throws Exception {
        return getProcessInstanceIds(processCode, LocalDateTime.now());
    }

    /**
     * 获取所有的审批实例ID列表
     * @param processCode 流程编号
     * @param startTime 开始时间
     * @return 返回实例编号列表
     * @throws Exception 请求异常
     */
    public List<String> getProcessInstanceIds(String processCode, LocalDateTime startTime) throws Exception {
        List<String> processInstanceIds = new ArrayList<>();
        ListProcessInstanceIdsResponseBody.ListProcessInstanceIdsResponseBodyResult instanceIds;
        String nextToken = "1"; //默认第一页
        do {
            instanceIds = getProcessInstanceIds(processCode, startTime, Long.valueOf(nextToken));
            processInstanceIds.addAll(instanceIds.getList());
            nextToken = instanceIds.getNextToken();
        } while ( nextToken != null );
        return processInstanceIds;
    }

    /**
     * 获取单个审批实例详情
     * @param processInstanceId 流程实例编号
     * @return 返回审批实例详情
     */
    public GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult getProcessInstance(String processInstanceId) throws Exception {
        Client client = createClient();
        GetProcessInstanceHeaders getProcessInstanceHeaders = new GetProcessInstanceHeaders();
        getProcessInstanceHeaders.xAcsDingtalkAccessToken = auth2Utils.getAccessToken();
        GetProcessInstanceRequest getProcessInstanceRequest = new GetProcessInstanceRequest().setProcessInstanceId(processInstanceId);
        GetProcessInstanceResponse instance = client.getProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new RuntimeOptions());
        return instance.getBody().getResult();
    }

}
